要掌握 C++ 物件的生命週期,就等於掌控其在 堆疊與堆區中的存在機制。複製控制定義了類別如何管理其 生命週期 透過兩個操作: 複製建構函式 以及 複製賦值運算子。
1. 初始化與賦值的差異
直接初始化(例如, string dots(10, '.'))會直接呼叫建構函式。然而, 複製初始化 (string s2 = dots)則依賴於複製建構函式。與初始化不同, 賦值 (trans = accum)會使用 operator=來覆蓋一個已存在的物件。關鍵限制是:複製建構函式的參數必須是參考型態(const Foo&);否則,以值的方式傳遞引數將會觸發一個 無限遞迴循環 的複製呼叫。
2. 合成的作用
如果你沒有定義這些成員,編譯器會提供 合成 版本,執行成員逐一複製。請注意:雖然對簡單型別足夠,但對於管理動態記憶體的類別來說,這些方法經常失效,導致懸空指標或重複釋放的問題。
main.py
TERMINALbash — 80x24
> Ready. Click "Run" to execute.
>
QUESTION 1
Why must the first parameter of a copy constructor be a reference type (usually const)?
To allow the compiler to optimize the code into a move operation.
To prevent infinite recursion during parameter initialization.
Because pointers are not allowed in constructor signatures.
To ensure the object is placed on the heap rather than the stack.
✅ Correct!
Correct! If the parameter were passed by value, calling the copy constructor would require a copy of the argument, which would call the copy constructor again, infinitely.❌ Incorrect
Think about how arguments are passed. Passing by value requires a copy... and how is that copy made?QUESTION 2
What is the primary difference between Copy Initialization and Direct Initialization?
Direct initialization uses the assignment operator; copy initialization does not.
Copy initialization always requires the 'new' keyword.
Direct initialization asks the compiler to find the best constructor; copy initialization requires the copy constructor.
There is no functional difference; they are just different syntax for the same call.
✅ Correct!
Exactly. Copy initialization happens when using '=', passing by value, or returning by value, and specifically requires the copy/move constructor.❌ Incorrect
Direct initialization (using parens or braces) matches against all available constructors, while copy initialization specifically invokes the copy constructor.QUESTION 3
Assume 'numbered' has a synthesized copy constructor that copies a unique ID 'mysn'. What happens if you run: numbered a, b = a, c = b;?
Each object (a, b, c) will have a unique 'mysn' value.
The program will fail to compile because IDs cannot be copied.
All three objects will share the exact same 'mysn' value.
Object 'a' will be reset to zero after the copy.
✅ Correct!
Since the synthesized version performs memberwise copy, it simply duplicates the value of 'mysn' from the source, defeating the uniqueness.❌ Incorrect
The synthesized copy constructor does not 'know' that 'mysn' is supposed to be unique; it just copies the bits.QUESTION 4
Which of the following would trigger a compilation error if the constructor 'vector<int>(int size)' is marked 'explicit'?
vector<int> v(10);vector<int> v = 10;f(vector<int>(10));vector<int>* p = new vector<int>(10);✅ Correct!
Correct! 'explicit' prevents the use of a constructor in copy-initialization contexts (like using '=').❌ Incorrect
Explicit constructors can be used for direct initialization but not for implicit conversions or copy initialization using '='.QUESTION 5
What should a well-behaved copy-assignment operator usually return?
void
A copy of the current object by value.
A reference to the left-hand operand (*this).
The memory address of the right-hand operand.
✅ Correct!
This is a best practice to remain consistent with built-in types and allow assignment chaining (e.g., a = b = c).❌ Incorrect
To allow chaining and maintain standard C++ behavior, return a reference to the modified object.Case Study: Identifying Copy Logistics
Trace object construction and assignment
Analyze the following snippet:
Point global;
Point foo_bar(Point arg) {
Point local = arg;
Point *heap = new Point(global);
*heap = local;
Point pa[2] = { local, *heap };
return *heap;
}
Q
1. How many times is the copy constructor called in the execution of foo_bar?
Solution:
The copy constructor is called 6 times: 1. Passing 'arg' by value. 2. Initializing 'local'. 3. Dynamic construction of '*heap' from 'global'. 4. Initializing pa[0]. 5. Initializing pa[1]. 6. Initializing the return value from '*heap'.
The copy constructor is called 6 times: 1. Passing 'arg' by value. 2. Initializing 'local'. 3. Dynamic construction of '*heap' from 'global'. 4. Initializing pa[0]. 5. Initializing pa[1]. 6. Initializing the return value from '*heap'.
Q
2. Does the line '*heap = local' use the copy constructor?
Solution:
No. This is an assignment operation on an already existing object pointed to by 'heap'. It uses the copy-assignment operator (
No. This is an assignment operation on an already existing object pointed to by 'heap'. It uses the copy-assignment operator (
operator=), not the copy constructor.Q
3. If the 'Message' class used synthesized copy control while managing a list of 'Folders', what potential danger arises?
Solution:
A 'shallow copy' would occur. The new 'Message' would point to the same internal resources as the old one, but the 'Folders' wouldn't know about the new message. This leads to broken links or double-free errors when the messages are destroyed.
A 'shallow copy' would occur. The new 'Message' would point to the same internal resources as the old one, but the 'Folders' wouldn't know about the new message. This leads to broken links or double-free errors when the messages are destroyed.